package main

import (
	"Jam/config"
	"bufio"
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"
)

func main() {
	var mode string
	flag.StringVar(&mode, "mode", "default", "运行模式 [default|clean|auto|startJar]")
	flag.Parse()

	// 验证模式有效性
	switch mode {
	case "default", "clean", "auto", "startJar":
		// 有效模式
	default:
		log.Fatalf("无效模式: %s，可用模式: default/clean/auto/startJar", mode)
	}

	// 清理模式处理
	if mode == "clean" {
		if err := DeleteAutoStart(); err != nil {
			log.Printf("删除开机启动失败: %v", err)
		} else {
			log.Println("已成功删除开机启动项")
		}
		return
	}

	// 初始化配置
	cfg, err := config.Load()
	if err != nil {
		log.Fatal("配置加载失败:", err)
	}

	// 初始化日志
	log.SetFlags(log.LstdFlags | log.Lshortfile)

	// 模式路由
	switch mode {
	case "auto":
		handleAutoMode(cfg)
	case "startJar":
		handleStartJar(cfg)
	default:
		handleDefaultMode(cfg)
	}
}

func handleAutoMode(cfg *config.AppConfig) {
	log.Println("开机启动模式")

	// 检查并执行自身更新
	checkSelfUpdate()

	// JAR管理
	jarPath, err := ManageVersion()
	if err != nil {
		log.Fatalf("JAR管理失败: %v", err)
	}

	log.Println("准备启动应急程序jar包")
	// 启动JAR
	cmd := exec.Command(filepath.Join(cfg.JDK.InstalledPath, "bin", "java"), "-jar", jarPath, "--task=sync")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		log.Fatal("启动失败:", err)
	}
}

func handleStartJar(cfg *config.AppConfig) {
	log.Println("启动模式 - 检查更新中...")

	// ⭐ 关键修复：启动前先检查自身更新
	checkSelfUpdate()

	// 检查并安装JDK
	if err := CheckAndInstallJDK(); err != nil {
		log.Fatalf("JDK安装失败: %v", err)
	}

	// ⭐ 关键修复：检查并更新JAR包
	jarPath, err := ManageVersion()
	if err != nil {
		log.Printf("警告: JAR版本管理失败: %v，尝试使用本地版本", err)
		jarPath, err = findLatestJar(cfg.Jar.StorageDir)
		if err != nil {
			log.Fatalf("未找到可用的JAR文件: %v", err)
		}
	}

	log.Println("启动应急程序的jar包")
	// 启动JAR
	javaPath := filepath.Join(cfg.JDK.InstalledPath, "bin", "java")
	log.Printf("java 路径为：" + javaPath)
	log.Printf("执行命令：%s -Dfile.encoding=UTF-8 -jar %s", javaPath, jarPath)

	cmd := exec.Command(javaPath,
		"-Dfile.encoding=UTF-8",
		"-jar",
		jarPath)

	// 获取 stdout
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Fatal("获取标准输出失败:", err)
	}

	cmd.Stderr = os.Stderr

	// 启动进程
	if err := cmd.Start(); err != nil {
		log.Fatal("启动失败:", err)
	}

	// 创建信号通道，用于控制浏览器打开
	browserOpened := make(chan bool, 1)
	// 读取输出并监听关键日志
	go func() {
		scanner := bufio.NewScanner(stdout)
		for scanner.Scan() {
			line := scanner.Text()
			fmt.Println(line)
			// 同样检查错误输出中的启动标志
			if strings.Contains(line, "Starting ProtocolHandler") ||
				strings.Contains(line, "Tomcat started on port") ||
				strings.Contains(line, "Started HeaApplication") {
				select {
				case browserOpened <- true:
					log.Println("检测到 Spring Boot 启动成功（从错误输出），准备打开浏览器")
					openBrowser("http://localhost:9090")
				default:
					// 通道已满，避免重复打开
				}
			}
		}
	}()

	// 等待 Java 进程退出
	if err := cmd.Wait(); err != nil {
		log.Fatal("JAR 运行失败:", err)
	}
}

func handleDefaultMode(cfg *config.AppConfig) {
	log.Println("默认启动模式")
	if !isAdmin() {
		log.Println("请以管理员身份运行，安装jdk和设置开机启动等需要管理员权限")
		return
	}

	// 检查并安装JDK
	if err := CheckAndInstallJDK(); err != nil {
		log.Fatalf("JDK安装失败: %v", err)
	}

	// JAR管理
	_, err := ManageVersion()
	if err != nil {
		log.Fatalf("JAR管理失败: %v", err)
	}

	// 把自身复制到程序目录
	exePath, _ := CopySelfToTarget()

	// 创建桌面快捷方式
	icon := exePath + `,0`
	shortcutPath, err := CreateDesktopShortcut(exePath, "-mode=startJar", icon)
	if err != nil {
		log.Printf("警告: 快捷方式设置失败: %v", err)
	} else {
		err := CopyFileToDir(shortcutPath, cfg.Jar.StorageDir)
		if err != nil {
			log.Printf("警告: 复制快捷方式失败: %v", err)
		} else {
			log.Printf("复制桌面快捷方式成功。")
		}
	}

	// 设置开机启动
	if err := SetupAutoStart(exePath); err != nil {
		log.Printf("警告: 开机启动设置失败: %v", err)
	}

	log.Println("所有操作已完成")
}

// ⭐ 新增：自身更新检查函数
func checkSelfUpdate() {
	exePath, err := os.Executable()
	if err != nil {
		log.Printf("无法获取程序路径: %v", err)
		return
	}

	newExePath := exePath + ".new"

	// 检查是否存在新版本
	if _, err := os.Stat(newExePath); os.IsNotExist(err) {
		return // 没有更新文件
	}

	log.Println("检测到新版本，准备更新...")

	// 备份当前版本
	backupPath := exePath + ".bak"
	os.Remove(backupPath) // 删除旧备份

	// 尝试重命名当前文件为备份
	if err := os.Rename(exePath, backupPath); err != nil {
		log.Printf("备份失败: %v", err)
		return
	}

	// 将新文件重命名为正式文件
	if err := os.Rename(newExePath, exePath); err != nil {
		log.Printf("更新失败: %v，恢复备份", err)
		os.Rename(backupPath, exePath) // 回滚
		return
	}

	log.Println("更新成功，重启程序...")

	// 重新启动程序
	cmd := exec.Command(exePath, os.Args[1:]...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	if err := cmd.Start(); err != nil {
		log.Printf("重启失败: %v", err)
		return
	}

	// 延迟删除备份文件（5秒后）
	go func() {
		time.Sleep(5 * time.Second)
		os.Remove(backupPath)
	}()

	// 退出当前程序
	os.Exit(0)
}
